#include "GY_ClippingRegion.h"
#include <QDebug>
#include <QGraphicsItem>
#include "Graphics/GY_GraphicsReflection.h"

GY_ClippingRegion::GY_ClippingRegion(const QString &guid, QGraphicsItem *parent) : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(QPointF(0,0));
    m_pClippingToolContainer = new GY_ClippingToolContainer(QString("%1_Tool").arg(guid),this);
    m_pRect = new QGraphicsRectItem(this);
    m_ChildrensMap.insert(m_pClippingToolContainer->getGuid(),m_pClippingToolContainer);
    this->addToGroup(m_pClippingToolContainer);
    setContainerEditPointF();
    updateDraw();
    setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemSendsScenePositionChanges);
}

GY_ClippingRegion::~GY_ClippingRegion()
{

}

void GY_ClippingRegion::setContainerEditPointF()
{
    QMap<QVariant,QPointF> editPoints = {
        {"Point1",m_PropertyInfoMap["Point1"].propertyValue.toPointF()},
        {"Point2",m_PropertyInfoMap["Point2"].propertyValue.toPointF()}
    };
    this->setEditPointF(editPoints);
}

GY_Object *GY_ClippingRegion::copyItem(const QString &guid)
{
    if(getUserData(GY_ENUM::IsCopy) == 1) {
//        return nullptr;
        GY_Object *tmp;
        this->copyItemSig(&tmp);
        //更新copyItem属性列表
        QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
        while (iterProperty != m_PropertyInfoMap.end()) {
            if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
                tmp->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
            }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
                ++iterProperty;
                continue;
            }else {
                tmp->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
            }
            ++iterProperty;
        }
        return tmp;
    }
    GY_Object* pObj;
    if(guid.isEmpty()) {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),this->getGuid()+"-"+QString::number(m_MyGuid));
        m_MyGuid++;
    }else {
        pObj = (GY_Object*)GY_GraphicsReflection::getInstance()->newInstanceObjectClass(this->metaObject()->className(),guid);
    }
    if(pObj == nullptr) {
        qDebug()<<this->getGuid()<<"isEmpty";
        return nullptr;
    }
    QVector<GY_Object *> childrens = m_pClippingToolContainer->getOrderChildrens();
    int childrensSize = childrens.size();
    for(int i=0;i<childrensSize;i++) {
//        if(childrens[i]->copyItem() == nullptr) {
//            qDebug()<<childrens[i]->getGuid()<<"isEmpty";
//            continue;
//        }
        ((GY_ContainerTransform*)pObj)->addItem(childrens[i]->copyItem());
    }

    QMap<QString,GY_PropertyInfo>::Iterator iterProperty = m_PropertyInfoMap.begin();
    while (iterProperty != m_PropertyInfoMap.end()) {
        if(((iterProperty.value().updateType)&PointOfRelative) == PointOfRelative) {
            pObj->updateProperty(iterProperty.key(), submittingPropertyValues(iterProperty.value().updateType,iterProperty.value().propertyValue,this));
        }else if(((iterProperty.value().updateType)&NotUpdate) == NotUpdate){
            ++iterProperty;
            continue;
        }else {
            pObj->updateProperty(iterProperty.key(), iterProperty.value().propertyValue);
        }
        ++iterProperty;
    }
    connect(pObj,&GY_Object::copyItemSig,this,&GY_Object::originalVersion);
    pObj->setUserData(GY_ENUM::IsCopy, QVariant::fromValue(1));
    return pObj;
}

bool GY_ClippingRegion::addItem(GY_Object *pItem)
{
    m_pClippingToolContainer->addItem((GY_Object*)pItem);
    updateDraw();
    return true;
}

bool GY_ClippingRegion::removItem(const QString &guid)
{
    return m_pClippingToolContainer->removItem(guid);
}

bool GY_ClippingRegion::removItem(const GY_Object *pItem)
{
    bool remove = m_pClippingToolContainer->removItem((GY_Object*)pItem);
    this->GY_ContainerTransform::removItem((GY_Object*)pItem);
    updateDraw();
    return remove;
}

void GY_ClippingRegion::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ClippingRegion::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //点1
    GY_PropertyInfo Point1PropertyInfo(this);
    Point1PropertyInfo.propertyName="Point1";
    Point1PropertyInfo.propertyValue=QPointF(-50,-50);
    Point1PropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    Point1PropertyInfo.propertyType = PointPropertyType;
    Point1PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ClippingRegion::updatePoint1;
    m_PropertyInfoMap.insert(Point1PropertyInfo.propertyName,Point1PropertyInfo);
    m_PropertyInfoMap[Point1PropertyInfo.propertyName].setConnect();

    //点2
    GY_PropertyInfo Point2PropertyInfo(this);
    Point2PropertyInfo.propertyName="Point2";
    Point2PropertyInfo.propertyValue=QPointF(50,50);
    Point2PropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    Point2PropertyInfo.propertyType = PointPropertyType;
    Point2PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ClippingRegion::updatePoint2;
    m_PropertyInfoMap.insert(Point2PropertyInfo.propertyName,Point2PropertyInfo);
    m_PropertyInfoMap[Point2PropertyInfo.propertyName].setConnect();

    //是否剪切
    GY_PropertyInfo EnableClippingPropertyInfo(this);
    EnableClippingPropertyInfo.propertyName="EnableClipping";
    EnableClippingPropertyInfo.propertyValue=true;
    EnableClippingPropertyInfo.updateType = Update|OrdinaryAttributes;
    EnableClippingPropertyInfo.propertyType = BoolPropertyType;
    EnableClippingPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ClippingRegion::updateEnableClipping;
    m_PropertyInfoMap.insert(EnableClippingPropertyInfo.propertyName,EnableClippingPropertyInfo);
    m_PropertyInfoMap[EnableClippingPropertyInfo.propertyName].setConnect();

    //隐藏
    GY_PropertyInfo isVisiblePropertyInfo(this);
    isVisiblePropertyInfo.propertyName="IsVisible";
    isVisiblePropertyInfo.propertyValue=true;
    isVisiblePropertyInfo.updateType = Update|OrdinaryAttributes;
    isVisiblePropertyInfo.propertyType = BoolPropertyType;
    isVisiblePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ClippingRegion::updateIsVisible;
    m_PropertyInfoMap.insert(isVisiblePropertyInfo.propertyName,isVisiblePropertyInfo);
    m_PropertyInfoMap[isVisiblePropertyInfo.propertyName].setConnect();

}

void GY_ClippingRegion::updateDraw()
{
    //是否剪切
    m_oldPoint1 = this->mapToScene(m_PropertyInfoMap["Point1"].propertyValue.toPointF());
    m_pClippingToolContainer->setIsCut(m_PropertyInfoMap["EnableClipping"].propertyValue.toBool());
    QPainterPath path;
    QPointF point1 = this->mapToScene(m_PropertyInfoMap["Point1"].propertyValue.toPointF());
    QPointF point2 = this->mapToScene(m_PropertyInfoMap["Point2"].propertyValue.toPointF());
    qreal width = point2.x()-point1.x();
    qreal height = point2.y()-point1.y();
    QRectF rect = QRectF(point1.x(),point1.y(), width, height);
    path.addRect(rect);
    this->removeFromGroup(m_pRect);
    m_pRect->setRect(m_PropertyInfoMap["Point1"].propertyValue.toPointF().x(),m_PropertyInfoMap["Point1"].propertyValue.toPointF().y(),width,height);
    this->addToGroup(m_pRect);
    this->setCenterPointF(this->mapFromScene(rect.center()));
    m_pClippingToolContainer->setShape(path);
}

bool GY_ClippingRegion::updatePoint1(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = this->mapFromScene(value.toPointF());
    this->setEditPointF(name,this->mapFromScene(value.toPointF()));
    updateDraw();
    return true;
}

bool GY_ClippingRegion::updatePoint2(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = this->mapFromScene(value.toPointF());
    this->setEditPointF(name,this->mapFromScene(value.toPointF()));
    updateDraw();
    return true;
}

bool GY_ClippingRegion::updateEnableClipping(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    updateDraw();
    return true;
}

bool GY_ClippingRegion::updateIsVisible(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value;
    this->setVisible(value.toBool());
    return true;
}

QVariant GY_ClippingRegion::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
{
    if(change==ItemPositionHasChanged)
    {
        //TODO:增加图形移动事件提交
        m_heightChange = this->mapToScene(m_PropertyInfoMap["Point1"].propertyValue.toPointF()).y()-m_oldPoint1.y();
        m_widthChange = this->mapToScene(m_PropertyInfoMap["Point1"].propertyValue.toPointF()).x()-m_oldPoint1.x();
        m_pClippingToolContainer->moveBy(-m_widthChange,-m_heightChange);
        updateDraw();
    }
    return GY_ContainerTransform::itemChange(change,value);
}
